package com.smart.framework;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

import com.smart.framework.bean.ControllerHelper;
import com.smart.framework.bean.Data;
import com.smart.framework.bean.Handler;
import com.smart.framework.bean.Param;
import com.smart.framework.bean.View;
import com.smart.framework.helper.BeanHelper;
import com.smart.framework.helper.ConfigHelper;
import com.smart.framework.util.ArrayUtil;
import com.smart.framework.util.CodecUtil;
import com.smart.framework.util.JsonUtil;
import com.smart.framework.util.ReflectionUtil;
import com.smart.framework.util.SteamUtil;
import com.smart.framework.util.StringUtil;

@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = -5859437900773306267L;

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		// 初始化helper类
		HelperLoader.init();
		// 获取ServletContext对象
		ServletContext servletContext = servletConfig.getServletContext();
		// 注册处理jsp的Servlet
		ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");
		jspServlet.addMapping(ConfigHelper.getAppJspPath() + "*");
		// 注冊處理靜態資源
		ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
		defaultServlet.addMapping(ConfigHelper.getAppAssetPath() + "*");
		// TODO Auto-generated method stub
		super.init();
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 获取请求方法与请求路径
		String requestMethod = req.getMethod().toLowerCase();
		String requestPath = req.getPathInfo();
		// 获取处理器
		Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
		if (handler != null) {
			// 获取Controller以及Bean实例
			Class<?> controllerClass = handler.getControllerClass();
			Object controllerBean = BeanHelper.getBean(controllerClass);
			// 创建请求参数对象
			@SuppressWarnings({ "unchecked", "rawtypes" })
			Map<String, Object> paramMap = new HashMap();
			Enumeration<String> paramNames = req.getParameterNames();
			while (paramNames.hasMoreElements()) {
				String paramName = paramNames.nextElement();
				String paramValue = req.getParameter(paramName);
				paramMap.put(paramName, paramValue);
			}
			String body = CodecUtil.decodeURL(SteamUtil.getString(req.getInputStream()));
			if (StringUtil.isNotEmpty(body)) {
				String[] params = StringUtils.split(body, "&");
				if (ArrayUtil.isNotEmpty(params)) {
					for (String param : params) {
						String[] array = StringUtils.split(param, "=");
						if (ArrayUtil.isNotEmpty(array) & array.length == 2) {
							String paramName = array[0];
							String paramValue = array[1];
							paramMap.put(paramName, paramValue);
						}
					}
				}
			}
			Param param = new Param(paramMap);
			// 调用action
			Method actionMethod = handler.getActionMethod();
			Object result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
			// 处理Action方法返回值
			if (result instanceof View) {
				// 返回JSP页面
				View view = (View) result;
				String path = view.getPath();
				if (StringUtil.isNotEmpty(path)) {
					if (path.startsWith("/")) {
						resp.sendRedirect(req.getContextPath() + path);
					} else {
						Map<String, Object> model = view.getModel();
						for (Map.Entry<String, Object> entity : model.entrySet()) {
							req.setAttribute(entity.getKey(), entity.getValue());
						}
						req.getRequestDispatcher(ConfigHelper.getAppJspPath() + path).forward(req, resp);
					}
				}
			} else if (result instanceof Data) {
				// 返回Data
				Data data = (Data) result;
				Object model = data.getModel();
				if (model != null) {
					resp.setContentType("application/json");
					resp.setCharacterEncoding("UTF-8");
					PrintWriter out = resp.getWriter();
					String json = JsonUtil.toJson(model);
					out.write(json);
					out.flush();
					out.close();
				}
			}

		}
	}

}
